﻿using Core.DataAccess.Model.Project.Information;
using Core.Framework.EntityExtend;
using Core.Framework.Model.Common;
using Core.Framework.Model.WebSockets;
using Core.Framework.Util.Common;
using Core.IBusiness.IComment;
using Core.IBusiness.IComment.Model;
using Core.IBusiness.IInformation;
using Core.IBusiness.IInformation.Model;
using Core.IBusiness.ISocketModule;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using Core.Framework.Util;
using Core.IBusiness.IPushModule;
using Core.Framework.Redis.Queue_Helper;

namespace Core.Business.Information
{
    public class Information : IInformation
    {
        private IQueue iQueue { get; set; }
        private ICommentModule iComment { get; set; }

        private IArticlePush iArticlePush { get; set; }

        public Information(ICommentModule iComment, IQueue iQueue, IArticlePush iArticlePush)
        {
            this.iComment = iComment;
            this.iQueue = iQueue;
            this.iArticlePush = iArticlePush;
        }

        public MethodResult<int> InformationAttributeExec(InformationAttribute model, SqlExecType sqlExecType)
        {
            return Utils.SqlExecType<ProjectInformationContext, InformationAttribute>(model,
                        sqlExecType,
                        a => a.Id == model.Id);
        }

        public MethodResult<int> InformationExec(InformationList model, SqlExecType sqlExecType)
        {
            var result = Utils.SqlExecType<ProjectInformationContext, InformationList>(model,
                        sqlExecType,
                        a => a.Id == model.Id & a.ProjectToken == model.ProjectToken,
                        afterAction: (context) =>
                        {

                            if (sqlExecType == SqlExecType.insert)
                            {
                                List<InformationAttribute> attrs = new List<InformationAttribute>();

                                attrs.Add(new InformationAttribute
                                {
                                    InfoKey = model.Id,
                                    RegTime = DateTime.Now,
                                    Type = (int)InformationAttributeEnum.Fabulous
                                });

                                attrs.Add(new InformationAttribute
                                {
                                    InfoKey = model.Id,
                                    RegTime = DateTime.Now,
                                    Type = (int)InformationAttributeEnum.Follow
                                });

                                attrs.Add(new InformationAttribute
                                {
                                    InfoKey = model.Id,
                                    Count = 0,
                                    RegTime = DateTime.Now,
                                    Type = (int)InformationAttributeEnum.ReadingCount
                                });

                                attrs.Add(new InformationAttribute
                                {
                                    InfoKey = model.Id,
                                    Count = 0,
                                    RegTime = DateTime.Now,
                                    Type = (int)InformationAttributeEnum.Share
                                });



                                if (null != model.Attributes)
                                {
                                    foreach (var item in model.Attributes)
                                    {
                                        item.InfoKey = model.Id;
                                        item.RegTime = DateTime.Now;
                                        attrs.Add(item);
                                    }
                                }


                                context
                                    .InformationAttribute
                                    .BulkInsert(attrs);

                            }

                        });




            return result;
        }


        public MethodResult<int> InformationTypeAttributeExec(InformationTypeAttribute model, SqlExecType sqlExecType)
        {
            return Utils.SqlExecType<ProjectInformationContext, InformationTypeAttribute>(model,
                        sqlExecType,
                        a => a.Id == model.Id);
        }

        public MethodResult<int> InformationTypeExec(InformationType model, SqlExecType sqlExecType)
        {
            return Utils.SqlExecType<ProjectInformationContext, InformationType>(model,
                        sqlExecType,
                        a => a.Id == model.Id);
        }




        public MethodResult<int> InformationRead(int infoKey, int userKey, int count = 1)
        {

            try
            {
                using (var context = new ProjectInformationContext())
                {

                    var model = context.InformationList.Where(a => a.Id == infoKey)
                        .Select(a => new
                        {
                            a.Id,
                            a.ProjectToken,
                            a.Title,
                            a.Content,
                            a.TypeKey
                        })
                        .FirstOrDefault();

                    if (model?.Id > 0)
                    {
                        context.InformationHistory.Add(new InformationHistory
                        {
                            ProjectToken = model.ProjectToken,
                            UserKey = userKey,
                            Content = new
                            {
                                infoKey = model.Id,
                                title = model.Title,
                                content = model.Content
                            }.TryToJson(),
                            RegTime = DateTime.Now,
                            TypeKey = model.TypeKey
                        });

                        context.InformationAttribute
                        .BulkUpdate($"Count += {count}")
                        .Where(a => a.InfoKey == infoKey && a.Type == (int)InformationAttributeEnum.ReadingCount);

                        int row = context.BeginSaveChanges(out string error);

                        return new MethodResult<int>
                        {
                            IsFinished = string.IsNullOrWhiteSpace(error),
                            Date = row,
                            Discription = error
                        };
                    }
                    else
                    {
                        return new MethodResult<int> { IsFinished = false, Discription = "信息不存在" };
                    }



                }
            }
            catch (Exception e)
            {
                return new MethodResult<int> { IsFinished = false, Date = 0, Discription = e.Message };
            }


        }




        public MethodResult<int> InformationStar(int infoKey, ApiClientInfo clientInfo)
        {
            var redis = new InformationRedisCache(infoKey, clientInfo.Key);
            redis.InfoStar();


            using (var context = new ProjectInformationContext())
            {
                var model = context.InformationList.Where(a => a.Id == infoKey).Select(a => new
                {
                    id = a.Id,
                    title = a.Title,
                    useKey = a.UserKey,
                    content = a.Content
                }).FirstOrDefault();

                if (model?.id > 0)
                {

                    #region Use iArticlePush Module

                    // 构造Content数据模型
                    var article = model.content.TryToEntity<ContentAndImages>(out string error)
                             ?? new ContentAndImages();

                    if (!string.IsNullOrWhiteSpace(error))
                    {
                        // 序列化失败的话，则直接使用content的数据
                        article.Content = model.content;
                    }

                    var content = new { content = article.GetContentSubStringByLength(), images = article.Images };

                    this.iArticlePush.InfoStar(new IBusiness.IPushModule.Model.InfoStarModel
                    {
                        Title = $"{clientInfo.UserName}赞了你发表的:{model.title}",
                        ClientToken = clientInfo.Token,
                        MessageKey = model.useKey.ToString(),
                        MessageContent = new IBusiness.IPushModule.Model.InfoStarContent
                        {
                            InfoKey = model.id,
                            Title = model.title,
                            Content = content.TryToJson()
                        }
                    });

                    #endregion

                    #region iQueue 推送 已过期部分
                    //iQueue.Publish(new QueryMessage
                    //{
                    //    MessageKey = model.useKey.ToString(),
                    //    Content = new
                    //    {
                    //        infoKey = model.id,
                    //        title = model.title,
                    //        content = model.content
                    //    }.TryToJson(),
                    //    Parameter = new { type = "infostar" }.TryToJson(),
                    //    ClientToken = clientToken,
                    //    MessageType = MessageTypeEnum.Single,
                    //    Template = "websocket"
                    //});
                    #endregion

                }
                else
                {
                    return new MethodResult<int> { IsFinished = false, Discription = "信息不存在" };
                }

            }


            return new MethodResult<int> { IsFinished = true, Date = 1 };
        }

        public MethodResult<int> InformationUnStar(int infoKey, int userKey, string clientToken)
        {
            var redis = new InformationRedisCache(infoKey, userKey);
            redis.InfoUnStar();




            return new MethodResult<int> { IsFinished = true, Date = 1 };
        }

        public MethodResult<int> InformationUnWatch(int infoKey, int userKey, string clientToken)
        {
            var redis = new InformationRedisCache(infoKey, userKey);
            redis.InfoUnWatch();
            return new MethodResult<int> { IsFinished = true, Date = 1 };
        }

        public MethodResult<int> InformationWatch(int infoKey, ApiClientInfo clientInfo)
        {

            MethodResult<bool> result = new MethodResult<bool> { IsFinished = true };


            using (var context = new ProjectInformationContext())
            {
                var model = context.InformationList.Where(a => a.Id == infoKey).Select(a => new
                {
                    id = a.Id,
                    title = a.Title,
                    useKey = a.UserKey,
                    content = a.Content
                }).FirstOrDefault();

                if (model?.id > 0)
                {
                    var redis = new InformationRedisCache(infoKey, clientInfo.Key);
                    redis.InfoWatch();

                    #region Use iArticlePush Module

                    // 构造Content数据模型
                    var article = model.content.TryToEntity<ContentAndImages>(out string error)
                             ?? new ContentAndImages();

                    if (!string.IsNullOrWhiteSpace(error))
                    {
                        // 序列化失败的话，则直接使用content的数据
                        article.Content = model.content;
                    }

                    var content = new { content = article.GetContentSubStringByLength(), images = article.Images };

                    this.iArticlePush.InfoWatch(
                        new IBusiness.IPushModule.Model.InfoWatchModel
                        {
                            Title = $"{clientInfo.UserName}关注了你发表的:{model.title}",
                            ClientToken = clientInfo.Token,
                            MessageKey = model.useKey.ToString(),
                            MessageContent = new IBusiness.IPushModule.Model.InfoWatchContent
                            {
                                InfoKey = model.id,
                                Title = model.title,
                                Content = content.TryToJson()
                            }
                        });

                    #endregion

                    #region iQueue 已过期

                    //result = iQueue.Publish(new QueryMessage
                    //{
                    //    MessageKey = model.useKey.ToString(),
                    //    Content = new
                    //    {
                    //        infoKey = model.id,
                    //        title = model.title,
                    //        content = model.content
                    //    }.TryToJson(),
                    //    Parameter = new { type = "infowatch" }.TryToJson(),
                    //    ClientToken = clientToken,
                    //    MessageType = MessageTypeEnum.Single,
                    //    Template = "websocket"
                    //});

                    #endregion


                }
                else
                {
                    return new MethodResult<int> { IsFinished = false, Discription = "信息不存在" };
                }

            }

            if (result.IsFinished)
            {
                return new MethodResult<int> { IsFinished = true, Date = 1 };
            }
            else
            {
                return new MethodResult<int> { IsFinished = true, Date = 1, Discription = $"通知失败：{result.Discription}" };
            }

        }





        public MethodResult<InformationList> GetInformationItem(InformationList model, bool isComment, List<InformationAttributeEnum> attributes = null)
        {
            try
            {
                using (var context = new ProjectInformationContext())
                {
                    model = context
                                .InformationList
                                .Where(a => a.Id == model.Id & a.ProjectToken == model.ProjectToken).FirstOrDefault();

                    // 是否查询属性
                    if (attributes?.Count > 0)
                    {
                        // 一次性查出所有内容的属性
                        model.Attributes =
                                context
                                    .InformationAttribute
                                    .Where(a =>
                                                model.Id == a.InfoKey
                                                && attributes.Select(b => (int)b).Contains(a.Type))
                                    .ToList();

                        this.StructureAttrs(model);

                    }

                }

                if (isComment)
                {
                    var ppp = new Pagination { rows = 10, page = 1 };
                    var commentResult = this.iComment.GetComments(
                        model.Id,
                        true,
                        ppp,
                        new List<CommentAttributeEnum> {
                    CommentAttributeEnum.Fabulous,
                    CommentAttributeEnum.Essence,
                    CommentAttributeEnum.IsAdvertisement,
                    CommentAttributeEnum.Product,
                    CommentAttributeEnum.RoofPlacement,
                    CommentAttributeEnum.Recommend
                        }, "info");

                    if (commentResult.IsFinished)
                    {
                        model.Comment = new Comment
                        {
                            Pagination = ppp,
                            Date = commentResult.Date
                        };
                    }
                }

                return new MethodResult<InformationList> { IsFinished = true, Date = model };
            }
            catch (Exception e)
            {
                return new MethodResult<InformationList> { IsFinished = false, Discription = e.Message };
            }
        }






        public MethodResult<List<InformationList>> GetInformationSearch(int Type, string projectToken, Pagination pagination, string search = null)
        {
            try
            {

                Expression<Func<InformationList, bool>> where = a => a.ProjectToken == projectToken;

                if (Type > 0)
                {
                    var typesResult = this.GetChildsTypeByTypeKey(Type);

                    if (typesResult.IsFinished)
                    {
                        where = a => typesResult.Date.Contains(a.TypeKey) && a.ProjectToken == projectToken;
                    }
                    else
                    {
                        return new MethodResult<List<InformationList>>
                        {
                            IsFinished = false,
                            Discription = typesResult.Discription
                        };
                    }
                }

                if (!string.IsNullOrWhiteSpace(search))
                {
                    where = where.And(a => a.Title.Contains(search));
                }

                using (var context = new ProjectInformationContext())
                {
                    var source = context
                        .InformationList
                        .Where(where)
                        .Pagination(pagination);

                    return new MethodResult<List<InformationList>>
                    {
                        IsFinished = true,
                        Date = source
                    };
                }
            }
            catch (Exception e)
            {
                return new MethodResult<List<InformationList>> { IsFinished = false, Discription = e.Message };
            }
        }


        public MethodResult<List<InformationList>> GetInformationAttributes(int Type, string projectToken, List<InformationAttributeEnum> attributes, Pagination pagination, string search = null, bool isGetCommtent = false)
        {


            try
            {
                Expression<Func<InformationList, bool>> where = a => a.ProjectToken == projectToken;

                if (Type > 0)
                {
                    var typesResult = this.GetChildsTypeByTypeKey(Type);

                    if (typesResult.IsFinished)
                    {
                        where = a => typesResult.Date.Contains(a.TypeKey) && a.ProjectToken == projectToken;
                    }
                    else
                    {
                        return new MethodResult<List<InformationList>>
                        {
                            IsFinished = false,
                            Discription = typesResult.Discription
                        };
                    }
                }


                if (!string.IsNullOrWhiteSpace(search))
                {
                    where = where.And(a => a.Title.Contains(search));
                }


                using (var context = new ProjectInformationContext())
                {
                    var source = context
                        .InformationList
                        .Where(where)
                        .Pagination(pagination);


                    // 是否查询属性
                    if (attributes?.Count > 0)
                    {

                        Expression<Func<InformationAttribute, bool>> whereAttrs =
                            a => attributes.Select(b => (int)b).Contains(a.Type) & source.Select(b => b.Id).Contains(a.InfoKey);

                        // 一次性查出所有内容的属性
                        var attrs =
                                context
                                    .InformationAttribute
                                    .Where(whereAttrs)
                                    .ToList();

                        foreach (var item in source)
                        {

                            item.Attributes = attrs.Where(a => a.InfoKey == item.Id).ToList();

                            this.StructureAttrs(item);

                            // 查询评论信息
                            if (isGetCommtent)
                            {
                                var ppp = new Pagination { rows = 3, page = 1, sord = "desc", sidx = "RegTime" };
                                var commentResult = this.iComment.GetComments(
                                                    item.Id,
                                                    false,
                                                    ppp,
                                                    new List<CommentAttributeEnum> {
                                                        CommentAttributeEnum.Fabulous
                                                    }, "info");

                                if (commentResult.IsFinished)
                                {
                                    item.Comment = new Comment
                                    {
                                        Pagination = ppp,
                                        Date = commentResult.Date
                                    };
                                }
                            }

                        }






                    }



                    return new MethodResult<List<InformationList>>
                    {
                        IsFinished = true,
                        Date = source
                    };
                }
            }
            catch (Exception e)
            {
                return new MethodResult<List<InformationList>> { IsFinished = false, Discription = e.Message };
            }



        }


        public MethodResult<List<InformationList>> GetInformationByAttributes(string projectToken, List<InformationAttributeEnum> attributes, Pagination pagination, int Type = 0, string search = null, bool isGetCommtent = false)
        {


            try
            {
                using (var context = new ProjectInformationContext())
                {

                    List<InformationAttributeEnum> _attributes = new List<InformationAttributeEnum>();
                    foreach (var item in attributes)
                    {
                        switch (item)
                        {
                            case InformationAttributeEnum.Fabulous:
                            case InformationAttributeEnum.Forward:
                            case InformationAttributeEnum.Follow:
                            case InformationAttributeEnum.ReadingCount:
                            case InformationAttributeEnum.Share:
                                break;

                            default:
                                _attributes.Add(item);
                                break;
                        }
                    }
                    Expression<Func<InformationAttribute, bool>> whereAttrs =
                                    a => _attributes.Select(b => (int)b).Contains(a.Type);

                    // 一次性查出所有内容的属性
                    var attrs =
                            context
                                .InformationAttribute
                                .Where(whereAttrs)
                                .ToList();


                    if (attrs?.Count > 0)
                    {
                        var infoKeys = attrs.Select(a => a.InfoKey).Distinct().ToList();

                        Expression<Func<InformationList, bool>> where =
                       a => infoKeys.Contains(a.Id) && a.ProjectToken == projectToken;


                        if (!string.IsNullOrWhiteSpace(search))
                        {
                            where = where.And(a => a.Title.Contains(search));
                        }

                        if (Type > 0)
                        {
                            var typesResult = this.GetChildsTypeByTypeKey(Type);

                            if (typesResult.IsFinished)
                            {
                                where = where.And(a => typesResult.Date.Contains(a.TypeKey));
                            }
                            else
                            {
                                return new MethodResult<List<InformationList>>
                                {
                                    IsFinished = false,
                                    Discription = typesResult.Discription
                                };
                            }

                        }


                        var source = context
                                    .InformationList
                                    .Where(where)
                                    .Pagination(pagination);


                        attrs = context
                                .InformationAttribute
                                .Where(a => source.Select(b => b.Id).Contains(a.InfoKey)  &&  attributes.Select(b => (int)b).Contains(a.Type))
                                .ToList();


                        foreach (var item in source)
                        {
                            item.Attributes = attrs.Where(a => a.InfoKey == item.Id).ToList();

                            foreach (var attr in attributes)
                            {
                                switch (attr)
                                {
                                    case InformationAttributeEnum.Fabulous:
                                        item.Attributes.Add(new InformationAttribute
                                        {
                                            InfoKey = item.Id,
                                            Type = (int)InformationAttributeEnum.Fabulous,
                                            Content = ""
                                        });
                                        break;
                                    case InformationAttributeEnum.ReadingCount:
                                        item.Attributes.Add(new InformationAttribute
                                        {
                                            InfoKey = item.Id,
                                            Type = (int)InformationAttributeEnum.ReadingCount,
                                            Content = ""
                                        });
                                        break;
                                    case InformationAttributeEnum.Follow:
                                        item.Attributes.Add(new InformationAttribute
                                        {
                                            InfoKey = item.Id,
                                            Type = (int)InformationAttributeEnum.Follow,
                                            Content = ""
                                        });
                                        break;
                                }
                            }


                            this.StructureAttrs(item);

                            // 查询评论信息
                            if (isGetCommtent)
                            {
                                var ppp = new Pagination { rows = 3, page = 1, sord = "desc", sidx = "RegTime" };
                                var commentResult = this.iComment.GetComments(
                                                    item.Id,
                                                    false,
                                                    ppp,
                                                    new List<CommentAttributeEnum> {
                                                        CommentAttributeEnum.Fabulous
                                                    }, "info");

                                if (commentResult.IsFinished)
                                {
                                    item.Comment = new Comment
                                    {
                                        Pagination = ppp,
                                        Date = commentResult.Date
                                    };
                                }
                            }
                        }

                        return new MethodResult<List<InformationList>>
                        {
                            IsFinished = true,
                            Date = source
                        };
                    }
                    else
                    {
                        return new MethodResult<List<InformationList>>
                        {
                            IsFinished = true
                        };
                    }



                }
            }
            catch (Exception e)
            {
                return new MethodResult<List<InformationList>> { IsFinished = false, Discription = e.Message };

            }




        }






        public MethodResult<List<InformationType>> SearchInformationType(int typeKey, string projectToken, Pagination pagination, string search = null)
        {
            try
            {

                Expression<Func<InformationType, bool>> where = a => a.UpKey == typeKey & a.ProjectToken == projectToken;

                if (!string.IsNullOrWhiteSpace(search))
                {
                    where = where.And(a => a.Title.Contains(search));
                }



                using (var context = new ProjectInformationContext())
                {
                    var list = context
                                .InformationType
                                .Where(where)
                                .Pagination(pagination)
                                .ToList();

                    // 是否查询属性
                    if (list?.Count > 0)
                    {

                        // 一次性查出所有属性
                        var attrs = context
                                .InformationTypeAttribute
                                .Where(a => list.Select(b => b.Id).Contains(a.TypeKey))
                                .ToList();


                        foreach (var item in list)
                        {
                            item.Attributes = attrs.Where(a => a.TypeKey == item.Id).ToList();
                        }

                    }

                    return new MethodResult<List<InformationType>> { IsFinished = true, Date = list };

                }

            }
            catch (Exception e)
            {
                return new MethodResult<List<InformationType>> { IsFinished = false, Discription = e.Message };
            }
        }

        public MethodResult<InformationType> GetInformationType(int typeKey, string projectToken)
        {
            try
            {
                using (var context = new ProjectInformationContext())
                {
                    var model = context
                                .InformationType
                                .Where(a =>
                                            a.Id == typeKey
                                            & a.ProjectToken == projectToken).FirstOrDefault();

                    if (model == null)
                    {
                        return new MethodResult<InformationType> { IsFinished = true, Date = model };
                    }


                    model.TopKey = model.TopKey > 0 ? model.TopKey : model.Id;

                    // 是否查询属性
                    if (model?.Id > 0)
                    {
                        // 一次性查出所有内容的属性
                        var types = context
                                .InformationType
                                .Where(a => a.TopKey == model.TopKey)
                                .ToList();

                        model.Attributes = context
                                                .InformationTypeAttribute
                                                .Where(a => a.TypeKey == model.Id)
                                                .ToList();


                        if (types?.Count > 0)
                        {
                            model.ChildNodes = TypeTree(model.ChildNodes, model.Id, types);

                            if (null != model.ChildNodes)
                            {
                                // 构造二级子集属性
                                var attrChilds = context
                                        .InformationTypeAttribute
                                        .Where(a => model.ChildNodes.Select(b => b.Id).Contains(a.TypeKey))
                                        .ToList();

                                foreach (var itemChild in model.ChildNodes)
                                {
                                    itemChild.Attributes
                                        = attrChilds.Where(a => a.TypeKey == itemChild.Id).ToList();
                                }
                            }

                        }

                    }

                    return new MethodResult<InformationType> { IsFinished = true, Date = model };

                }

            }
            catch (Exception e)
            {
                return new MethodResult<InformationType> { IsFinished = false, Discription = e.Message };
            }
        }

        public MethodResult<List<InformationType>> GetInformationTypes(string projectToken, Pagination pagination)
        {
            try
            {
                // 分类属性 只支持 2级
                using (var context = new ProjectInformationContext())
                {
                    var list = context
                                .InformationType
                                .Where(a => a.ProjectToken == projectToken & a.TopKey == 0).ToList();

                    // 是否查询属性
                    if (list?.Count > 0)
                    {
                        // 一次性查出所有子分类
                        var types = context
                                .InformationType
                                .Where(a => list.Select(b => b.Id).Contains(a.TopKey))
                                .Pagination(pagination);

                        // 一次性查出所有子属性
                        var attrs = context
                                .InformationTypeAttribute
                                .Where(a => types.Union(list).Select(b => b.Id).Contains(a.TypeKey))
                                .ToList();


                        if (types.Count > 0)
                        {
                            foreach (var item in list)
                            {
                                item.Attributes = attrs.Where(a => a.TypeKey == item.Id).ToList();

                                item.ChildNodes = TypeTree(item.ChildNodes, item.Id, types);


                                // 构造二级子集属性
                                if (null != item.ChildNodes)
                                {
                                    var attrChilds = context
                                        .InformationTypeAttribute
                                        .Where(a => item.ChildNodes.Select(b => b.Id).Contains(a.TypeKey))
                                        .ToList();

                                    if (null != attrChilds)
                                        foreach (var itemChild in item.ChildNodes)
                                        {
                                            itemChild.Attributes
                                                = attrChilds.Where(a => a.TypeKey == item.Id).ToList();
                                        }
                                }
                            }
                        }

                    }

                    return new MethodResult<List<InformationType>> { IsFinished = true, Date = list };

                }

            }
            catch (Exception e)
            {
                return new MethodResult<List<InformationType>> { IsFinished = false, Discription = e.Message };
            }
        }


        public MethodResult<List<InformationList>> GetInformationUser(int userKey, string projectToken, Pagination pagination, List<InformationAttributeEnum> attributes, int type, string search = null)
        {
            try
            {
                Expression<Func<InformationList, bool>> where =
                    a => a.UserKey == userKey && a.ProjectToken == projectToken;

                if (type > 0)
                {
                    var typesResult = this.GetChildsTypeByTypeKey(type);

                    if (typesResult.IsFinished)
                    {
                        where = where.And(a => typesResult.Date.Contains(a.TypeKey));
                    }
                    else
                    {
                        return new MethodResult<List<InformationList>>
                        {
                            IsFinished = false,
                            Discription = typesResult.Discription
                        };
                    }

                }

                if (!string.IsNullOrWhiteSpace(search))
                {
                    where = where.And(a => a.Title.Contains(search));
                }


                using (var context = new ProjectInformationContext())
                {
                    var source = context
                        .InformationList
                        .Where(where)
                        .Pagination(pagination);


                    // 是否查询属性
                    if (attributes?.Count > 0)
                    {

                        Expression<Func<InformationAttribute, bool>> whereAttrs =
                            a => attributes.Select(b => (int)b).Contains(a.Type) & source.Select(b => b.Id).Contains(a.InfoKey); ;

                        // 一次性查出所有内容的属性
                        var attrs =
                                context
                                    .InformationAttribute
                                    .Where(whereAttrs)
                                    .ToList();

                        foreach (var item in source)
                        {
                            item.Attributes = attrs.Where(a => a.InfoKey == item.Id).ToList();
                            this.StructureAttrs(item);
                        }

                    }



                    return new MethodResult<List<InformationList>>
                    {
                        IsFinished = true,
                        Date = source
                    };
                }
            }
            catch (Exception e)
            {
                return new MethodResult<List<InformationList>> { IsFinished = false, Discription = e.Message };
            }

        }




        public MethodResult<List<InformationList>> GetInformationUserByAttributes(int userKey, string projectToken,
            Pagination pagination, List<InformationAttributeEnum> attributes, bool isGetCommtent, string search = null)
        {


            try
            {
                using (var context = new ProjectInformationContext())
                {

                    var attriUsers = new List<int>();
                    var attris = new List<int>();

                    foreach (var attr in attributes)
                    {
                        switch (attr)
                        {
                            case InformationAttributeEnum.Fabulous:
                            case InformationAttributeEnum.Forward:
                            case InformationAttributeEnum.Follow:
                            case InformationAttributeEnum.Share:
                                attriUsers.Add((int)attr);
                                break;
                            default:
                                attris.Add((int)attr);
                                break;
                        }
                    }

                    Expression<Func<InformationAttribute, bool>> whereAttrs = a => false;

                    if (attriUsers.Count > 0)
                    {
                        whereAttrs = whereAttrs.Or(a => attriUsers.Contains(a.Type) && a.Content.Contains($",{userKey},"));
                    }

                    if (attris.Count > 0)
                    {
                        whereAttrs = whereAttrs.Or(a => attris.Contains(a.Type));
                    }

                    // 一次性查出所有内容的属性
                    var infos =
                            context
                                .InformationAttribute
                                .Where(whereAttrs)
                                .ToList() ?? new List<InformationAttribute>();

                    var redis = new InformationRedisCache(0, userKey);

                    var infoKeys = infos.Select(a => a.InfoKey);

                    foreach (var attr in attributes)
                    {
                        switch (attr)
                        {
                            case InformationAttributeEnum.Fabulous:
                                var stars = redis.GetInfoUserStar().Select(a => a.ToInt()).ToList();
                                infoKeys = infoKeys.Union(stars).ToList();
                                break;
                            case InformationAttributeEnum.Follow:
                                var watch = redis.GetInfoUserWatch().Select(a => a.ToInt()).ToList();
                                infoKeys = infoKeys.Union(watch).ToList();
                                break;
                        }
                    }

                    if (infoKeys.Count() > 0)
                    {

                        var kkk = infoKeys.Distinct().ToList();

                        Expression<Func<InformationList, bool>> where =
                       a => kkk.Contains(a.Id) && a.ProjectToken == projectToken;

                        if (!string.IsNullOrWhiteSpace(search))
                        {
                            where = where.And(a => a.Title.Contains(search));
                        }


                        var source = context
                                    .InformationList
                                    .Where(where)
                                    .Pagination(pagination);


                        foreach (var item in source)
                        {
                            item.Attributes = infos.Where(a => a.InfoKey == item.Id).ToList();

                            foreach (var attr in attributes)
                            {
                                switch (attr)
                                {
                                    case InformationAttributeEnum.Fabulous:
                                        item.Attributes.Add(new InformationAttribute
                                        {
                                            InfoKey = item.Id,
                                            Type = (int)InformationAttributeEnum.Fabulous,
                                            Content = ""
                                        });
                                        break;
                                    case InformationAttributeEnum.ReadingCount:
                                        item.Attributes.Add(new InformationAttribute
                                        {
                                            InfoKey = item.Id,
                                            Type = (int)InformationAttributeEnum.ReadingCount,
                                            Content = ""
                                        });
                                        break;
                                    case InformationAttributeEnum.Follow:
                                        item.Attributes.Add(new InformationAttribute
                                        {
                                            InfoKey = item.Id,
                                            Type = (int)InformationAttributeEnum.Follow,
                                            Content = ""
                                        });
                                        break;
                                }
                            }

                            this.StructureAttrs(item);

                            // 查询评论信息
                            if (isGetCommtent)
                            {
                                var ppp = new Pagination { rows = 3, page = 1, sord = "desc", sidx = "RegTime" };
                                var commentResult = this.iComment.GetComments(
                                                    item.Id,
                                                    false,
                                                    ppp,
                                                    new List<CommentAttributeEnum> {
                                                        CommentAttributeEnum.Fabulous
                                                    }, "info");

                                if (commentResult.IsFinished)
                                {
                                    item.Comment = new Comment
                                    {
                                        Pagination = ppp,
                                        Date = commentResult.Date
                                    };
                                }
                            }
                        }

                        return new MethodResult<List<InformationList>>
                        {
                            IsFinished = true,
                            Date = source
                        };
                    }
                    else
                    {
                        return new MethodResult<List<InformationList>>
                        {
                            IsFinished = true
                        };
                    }



                }
            }
            catch (Exception e)
            {
                return new MethodResult<List<InformationList>> { IsFinished = false, Discription = e.Message };

            }




        }





        public MethodResult<List<InformationType>> GetInformationTypeUser(int userKey, string projectToken, Pagination pagination, int typeKey = 0)
        {
            try
            {

                Expression<Func<InformationType, bool>> where =
                       a => a.ProjectToken == projectToken && a.UserKey == userKey;

                if (typeKey > 0)
                {
                    where = where.And(a => a.UpKey == typeKey);
                }
                else
                {
                    where = where.And(a => a.TopKey == 0);
                }


                // 分类属性 只支持 2级
                using (var context = new ProjectInformationContext())
                {
                    var list = context
                                .InformationType
                                .Where(where)
                                .ToList();

                    // 是否查询属性
                    if (list?.Count > 0)
                    {
                        // 一次性查出所有子分类
                        var types = typeKey == 0 ? null : context
                                .InformationType
                                .Where(a => list.Select(b => b.TopKey).Distinct().Contains(a.TopKey))
                                .Pagination(pagination);

                        // 一次性查出所有子属性
                        var attrs = typeKey == 0 ? null : context
                                .InformationTypeAttribute
                                .Where(a => types.Select(b => b.Id).Contains(a.TypeKey))
                                .ToList();


                        if (types.Count > 0)
                        {
                            foreach (var item in list)
                            {
                                item.Attributes = attrs.Where(a => a.TypeKey == item.Id).ToList();

                                item.ChildNodes = TypeTree(item.ChildNodes, item.Id, types);


                                // 构造二级子集属性
                                if (null != item.ChildNodes)
                                {
                                    var attrChilds = context
                                        .InformationTypeAttribute
                                        .Where(a => item.ChildNodes.Select(b => b.Id).Contains(a.TypeKey))
                                        .ToList();

                                    if (null != attrChilds)
                                        foreach (var itemChild in item.ChildNodes)
                                        {
                                            itemChild.Attributes
                                                = attrChilds.Where(a => a.TypeKey == item.Id).ToList();
                                        }
                                }
                            }
                        }

                    }

                    return new MethodResult<List<InformationType>> { IsFinished = true, Date = list };

                }

            }
            catch (Exception e)
            {
                return new MethodResult<List<InformationType>> { IsFinished = false, Discription = e.Message };
            }
        }




        public MethodResult<List<InformationHistory>> GetInformationHistoryUser(int userKey, int type, string projectToken, Pagination pagination)
        {

            try
            {
                using (var context = new ProjectInformationContext())
                {

                    Expression<Func<InformationHistory, bool>> where
                        = a => a.ProjectToken == projectToken && a.UserKey == userKey;

                    if (type > 0)
                    {
                        var typesResult = this.GetChildsTypeByTypeKey(type);

                        if (typesResult.IsFinished)
                        {
                            where = where.And(a => typesResult.Date.Contains(a.TypeKey));
                        }
                        else
                        {
                            return new MethodResult<List<InformationHistory>>
                            {
                                IsFinished = false,
                                Discription = typesResult.Discription
                            };
                        }

                    }



                    var list = context
                                .InformationHistory
                                .Where(where)
                                .OrderByDescending(a => a.RegTime)
                                .Pagination(pagination);

                    return new MethodResult<List<InformationHistory>> { IsFinished = true, Date = list };

                }

            }
            catch (Exception e)
            {
                return new MethodResult<List<InformationHistory>> { IsFinished = false, Discription = e.Message };
            }


        }



        #region Common

        /// <summary>
        /// 获取指定分类所有子集ID
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        private MethodResult<List<int>> GetChildsTypeByTypeKey(int type)
        {
            try
            {
                List<int> list = new List<int>();

                using (var context = new ProjectInformationContext())
                {
                    var model = context
                                .InformationType
                                .Where(a => a.Id == type).FirstOrDefault();

                    // 是否查询属性
                    if (model?.Id > 0)
                    {
                        list.Add(model.Id);

                        model.TopKey = model.TopKey > 0 ? model.TopKey : model.Id;


                        // 一次性查出所有内容的属性
                        var types = context
                                .InformationType
                                .Where(a => a.TopKey == model.TopKey)
                                .ToList();


                        if (types.Count > 0)
                        {
                            model.ChildNodes = TypeTree(model.ChildNodes, model.Id, types, list);
                        }

                    }

                }

                return new MethodResult<List<int>> { IsFinished = true, Date = list };
            }
            catch (Exception e)
            {
                return new MethodResult<List<int>> { IsFinished = false, Discription = e.Message };
            }
        }


        /// <summary>
        /// 构建树形分类数据
        /// </summary>
        /// <param name="nodes"></param>
        /// <param name="parentID"></param>
        /// <param name="sources"></param>
        List<InformationType> TypeTree(List<InformationType> nodes, int parentID, List<InformationType> sources, List<int> nodeKeys = null)
        {
            var tempTree = sources.Where(item => item.UpKey == parentID).ToList();

            if (tempTree.Count > 0)
            {
                nodes = new List<InformationType>();

                foreach (var item in tempTree)
                {
                    if (nodeKeys != null)
                        nodeKeys.Add(item.Id);

                    nodes.Add(item);
                    item.ChildNodes = TypeTree(item.ChildNodes, item.Id, sources, nodeKeys);
                }

                return nodes;
            }

            return null;

        }



        private InformationList StructureAttrs(InformationList item)
        {

            var redis = new InformationRedisCache(item.Id, 0);

            item.Attributes = item.Attributes.Select(a =>
            {


                if (a.Type == (int)InformationAttributeEnum.Fabulous)
                {

                    var stars = redis.GetInfoStar().Select(b => b.Key);

                    if (string.IsNullOrWhiteSpace(a.Content))
                    {
                        a.Content = string.Join(',', stars);
                    }
                    else
                    {

                        var dbstars = a.Content.TrimEnd(',').TrimStart(',').Split(',').ToList();

                        // 处理redis获取到的数据
                        var redisStars = stars.ToList();

                        // 合并结果集并去重
                        a.Content = string.Join(',', dbstars.Union(redisStars));
                    }

                }


                if (a.Type == (int)InformationAttributeEnum.Follow)
                {
                    var watchs = redis.GetInfoWatch().Select(b => b.Key);

                    if (string.IsNullOrWhiteSpace(a.Content))
                    {
                        a.Content = string.Join(',', watchs);
                    }
                    else
                    {

                        var dbwatchs = a.Content.TrimEnd(',').TrimStart(',').Split(',').ToList();

                        // 处理redis获取到的数据
                        var redisWatchs = watchs.ToList();

                        // 合并结果集并去重
                        a.Content = string.Join(',', dbwatchs.Union(redisWatchs));
                    }
                }

                return a;

            }).ToList();

            return item;
        }


        #endregion

    }
}
